#include "point.h"
#include <math.h>

using namespace m3d;

SPoint3F::SPoint3F( void ){ };

SPoint3F::SPoint3F( float _x, float _y, float _z )
:x(_x),y(_y),z(_z)
{};

SPoint3F SPoint3F::operator + ( const SPoint3F& b ) const
{
	return SPoint3F(x+b.x, y+b.y, z+b.z);
}

SPoint3F SPoint3F::operator - ( const SPoint3F& b ) const
{
	return SPoint3F(x-b.x, y-b.y, z-b.z);
}

SPoint3F SPoint3F::operator * ( float _scalar ) const
{
	return SPoint3F(x*_scalar, y*_scalar, z*_scalar);
}

SPoint3F SPoint3F::operator / ( float _scalar ) const
{
	return SPoint3F(x/_scalar, y/_scalar, z/_scalar);
}

SPoint3F& SPoint3F::operator += ( const SPoint3F& b )
{
	x += b.x; 
	y += b.y;
	z += b.z;
	return *this;
}

SPoint3F& SPoint3F::operator -= ( const SPoint3F& b )
{
	x -= b.x; 
	y -= b.y;
	z -= b.z;
	return *this;
}

SPoint3F& SPoint3F::operator *= ( float _scalar )
{
	x *= _scalar;
	y *= _scalar;
	z *= _scalar;
	return *this;
}

SPoint3F& SPoint3F::operator /= ( float _scalar )
{
	x /= _scalar;
	y /= _scalar;
	z /= _scalar;
	return *this;
}

SPoint3F& SPoint3F::operator = ( const SPoint3F& b )
{
	x = b.x; 
	y = b.y;
	z = b.z;
	return *this;
}

bool SPoint3F::operator == ( const SPoint3F& b ) const
{ 
	return b.x == x && b.y == y && b.z == z; 
};

bool SPoint3F::operator != ( const SPoint3F& b ) const
{ 
	return b.x != x || b.y != y || b.z != z;
};

float SPoint3F::Length( void ) const
{ 
	double l = x*(double)x+y*(double)y+z*(double)z;
	if( l )
		l = sqrt(l);
	return (float)l;
};

double SPoint3F::SqLength( void ) const
{ 
	return x*(double)x+y*(double)y+z*(double)z;
};

float SPoint3F::Dot( const SPoint3F& _v ) const
{
	return x*_v.x + y*_v.y + z*_v.z;
};

SPoint3F& SPoint3F::Normalize( void )
{
	double l = SqLength();
	if( l )
	{
		l = sqrt(l);
		x /= (float)l;
		y /= (float)l;
		z /= (float)l;
	}
	return *this;
};

float SPoint3F::AngleWith( const SPoint3F& v ) const
{
   return (float)acos( ((*this).Dot(v)) / (this->Length()*v.Length()) );
}

SPoint3F SPoint3F::Cross( const SPoint3F& vector ) const 
{ 
	return SPoint3F(	y * vector.z - z * vector.y, 
						z * vector.x - x * vector.z, 
						x * vector.y - y * vector.x
					); 
};

SPoint3F& SPoint3F::Cross( const SPoint3F& vector1, const SPoint3F& vector2 )
{ 
	x = vector1.y * vector2.z - vector1.z * vector2.y;
	y = vector1.z * vector2.x - vector1.x * vector2.z;
	z = vector1.x * vector2.y - vector1.y * vector2.x;
	return *this;
};
